/**
 * @author yinyuejia
 * @file 菜单 & 路由
 */

import storage from '@/utils/storage';
import tool from '@/utils/tool';
import router from '@/router';
import { mainRoute, defaultRoutes } from '@/router/constantRoute';
import preload from '@/utils/preload';
import typeUtil from '@/utils/type';
import loadsh from 'lodash';

const defaultState = {
  cacheRoutes: [], // 需要被缓存的路由
  expandLeftMenu: true, // 菜单折叠展开状态
  activeLeftMenuIndex: '', // 左侧哪个菜单选中了
  leftMenuList: [], // 左侧菜单list
  breadcrumb: [], // 面包屑数组
  tagList: [], // tag list
  activeTag: '', // 激活哪个tag
  tagChildren: {}, // 同一个tag页签，可能包含不同的子页面，该tag删除时，同时删除子页面
  routeLoaded: false, // 首次进入设置路由
};
const DEFAULTSTATE: any = loadsh.cloneDeep(defaultState);
const storageKey = 'menu';

// 处理菜单项，防止传入的不符合路由规则
const handleUserMenus = function (menuList: any) {
  return menuList.map((menu: any) => {
    const item: any = {};
    item.code = menu.code;
    item.name = menu.name;
    item.url = menu.url;
    item.component = menu.component;
    /* eslint-disable */
    item.meta = menu.meta ? (typeUtil.isString(menu.meta) ? JSON.parse(menu.meta) : menu.meta) : {}; // 防止后端meta字段过来的是JSON字符串
    /* eslint-enable */
    item.order = menu.order || 0;
    item.icon = menu.icon;
    if (menu.children && menu.children.length > 0) {
      item.children = handleUserMenus(menu.children); // 递归处理
    } else {
      item.children = [];
    }
    return item;
  });
};

// 处理系统路由，防止传入的不符合路由规则
const handleSystemRoutes = function (routes: any) {
  return routes.map((route: any) => {
    route.meta = route.meta ? route.meta : {};
    if (!route.meta.title) {
      route.meta.title = route.title || route.name;
    }
    route.component = typeUtil.isString(route.component) ? preload(route.component) : route.component; // 预加载
    route.meta.fullscreen =
      route.fullscreen === true ||
      route.fullscreen === 'true' ||
      route.meta.fullscreen === true ||
      route.meta.fullscreen === 'true';
    return route;
  });
};

// 用户菜单转路由
const convertUserMenusToRoutes = function (payload: any) {
  const allRoutes = router.getRoutes();
  return tool
    .flatMap(payload.menuList)
    .filter((a: any) => !(a.children && a.children.length > 0))
    .map((menu: any) => {
      const item: any = {};
      item.name = menu.code;
      item.path = menu.url;
      if (menu.component) {
        item.component = typeUtil.isString(menu.component) ? preload(menu.component) : menu.component; // 预加载
      }
      if (allRoutes.filter((r: any) => r.name === item.name).length > 0) {
        const preRoute = allRoutes.filter((r: any) => r.name === item.name)[0];
        if (!menu.component && preRoute.components) {
          item.component = preRoute.components.default;
        }
        item.meta = { ...preRoute.meta, ...menu.meta };
      } else {
        item.meta = menu.meta;
      }
      if (!item.meta.title) {
        item.meta.title = menu.name;
      }
      item.meta.fullscreen = menu.fullscreen === true || menu.fullscreen === 'true';
      return item;
    });
};

// 设置路由
const setRouteFunc = function (state: any, payload: any) {
  const userRoutes = convertUserMenusToRoutes(payload);
  userRoutes.filter((a: any) => a.meta.fullscreen).forEach((r: any) => router.addRoute(r));
  // ts-ignore
  mainRoute.children = mainRoute.children
    ? mainRoute.children.concat(userRoutes.filter((a: any) => !a.meta.fullscreen))
    : [];
  if (!state.routeLoaded) {
    // 加载系统路由
    const constantRoutes = handleSystemRoutes(defaultRoutes);
    constantRoutes.filter((a: any) => a.meta.fullscreen).forEach((r: any) => router.addRoute(r));
    mainRoute.children = mainRoute.children.concat(constantRoutes.filter((a: any) => !a.meta.fullscreen));
  }
  router.addRoute(mainRoute);
  state.routeLoaded = true;
};

export default {
  state: defaultState,
  mutations: {
    // 重新加载
    reloadMenu(state: any) {
      const data = storage.get(storageKey);
      if (data) {
        Object.keys(data).forEach((k) => {
          state[k] = data[k];
        });
      }
    },

    // 清除缓存
    clear(state: any) {
      Object.keys(DEFAULTSTATE).forEach((k) => {
        state[k] = loadsh.cloneDeep(DEFAULTSTATE[k]);
      });
      storage.clear(storageKey);
    },

    // 设置路由
    setRoute(state: any) {
      setRouteFunc(state, { menuList: state.leftMenuList });
    },

    // 设置菜单
    setLeftMenu(state: any, payload: any) {
      // 加入首页菜单
      const menuList = handleUserMenus(payload.menuList || []);
      setRouteFunc(state, { menuList });

      state.leftMenuList = menuList;
      storage.set(`${storageKey}.leftMenuList`, menuList);
    },

    // 折叠、展开菜单
    toggleLeftMenuExpandState(state: any) {
      state.expandLeftMenu = !state.expandLeftMenu;
      storage.set(`${storageKey}.expandLeftMenu`, state.expandLeftMenu);
    },

    // 设置菜单选中状态
    setActiveLeftMenu(state: any, payload: any) {
      state.activeLeftMenuIndex = payload;
    },

    // 设置面包屑路径
    setBreadCrumb(state: any, payload: any) {
      state.breadcrumb = payload.breadcrumb;
    },

    // 设置哪个tags激活
    setActiveTag(state: any, tag: any) {
      state.activeTag = tag;
      storage.set(`${storageKey}.activeTag`, tag);
    },

    // 设置taglist
    setTagList(state: any, tagList: any) {
      state.tagList = tagList;
      storage.set(`${storageKey}.tagList`, tagList);
    },

    // 增加tag
    addTag(state: any, tag: any) {
      const tagList = state.tagList || [];
      tagList.push(tag);
      state.tagList = tagList;
      storage.set(`${storageKey}.tagList`, tagList);
    },

    // 设置子tag
    setTagChildren(state: any, payload: any) {
      if (state.tagChildren[payload.key]) {
        state.tagChildren[payload.key].push(payload.value);
      } else {
        state.tagChildren[payload.key] = [payload.value];
      }
    },

    // 增加缓存路由
    addCacheRoute(state: any, name: any) {
      if (state.cacheRoutes.indexOf(name) < 0) {
        state.cacheRoutes.push(name);
      }
    },

    // 移除缓存路由
    removeCacheRoute(state: any, name: any) {
      let arr: any = [];
      if (typeUtil.isString(name)) {
        arr.push(name);
      } else if (typeUtil.isArray(name)) {
        arr = arr.concat(name);
      }
      let childArr: any = [];
      arr.forEach((key: any) => {
        const child = state.tagChildren[key];
        if (child) {
          childArr = childArr.concat(child);
        }
      });
      arr = arr.concat(childArr);
      if (arr.length > 0) {
        state.cacheRoutes = state.cacheRoutes.filter((a: any) => arr.indexOf(a) < 0);
      }
    },

    // 设置缓存路由
    setCacheRoute(state: any, names: any) {
      state.cacheRoutes = names;
    },
  },
  getters: {
    // 左侧菜单数组
    leftMenuList(state: any) {
      const menuList = defaultRoutes
        .filter((a) => a.name === 'Home')
        .map((menu: any) => {
          const item: any = {};
          item.code = menu.name;
          item.name = menu.title || menu.meta.title || menu.name;
          item.url = menu.path;
          item.icon = menu.icon;
          item.component = menu.component;
          /* eslint-disable */
          item.meta = menu.meta ? (typeUtil.isString(menu.meta) ? JSON.parse(menu.meta) : menu.meta) : {};
          /* eslint-enable */
          item.order = -99;
          item.children = [];
          return item;
        });
      function filterMenus(menus: any) {
        const newMenuList = menus.filter((a: any) => !a.meta.menu).sort((a: any, b: any) => a.order - b.order);
        newMenuList.forEach((menu: any) => {
          if (menu.children && menu.children.length > 0) {
            menu.children = filterMenus(menu.children);
          }
        });
        return newMenuList;
      }
      return menuList.concat(filterMenus(state.leftMenuList));
    },
  },
};
